/**
 * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.md.
 */

/**
 * @module alignment/alignmentcommand
 */

import Command from '@ckeditor/ckeditor5-core/src/command';
import first from '@ckeditor/ckeditor5-utils/src/first';

const OUTDENT = 'outdent';
const INDENT = 'indent';

export default class Outdentcommand extends Command {

	/**
	 * Updates the command's {@link #value} and {@link #isEnabled} based on the current selection.
	 */
	refresh() {
		const model =this.editor.model;
		const doc = model.document;

		const blocks = Array.from( doc.selection.getSelectedBlocks() );
		if(blocks[ 0 ]!=null){
			const currentAlignment = blocks[ 0 ].getAttribute( INDENT );
			if(currentAlignment!=null&&parseFloat(currentAlignment)>=20){
				this.isEnabled = true;
			}else{
				this.isEnabled = false;
			}
		}

	}

	/**
	 * Executes the command &mdash; applies the attribute to the selection or removes it from the selection.
	 *
	 * If the command is active (`value == true`), it will remove attributes. Otherwise, it will set attributes.
	 *
	 * The execution result differs, depending on the {@link module:engine/model/document~Document#selection}:
	 *
	 * * If the selection is on a range, the command applies the attribute to all nodes in that range
	 * (if they are allowed to have this attribute by the {@link module:engine/model/schema~Schema schema}).
	 * * If the selection is collapsed in a non-empty node, the command applies the attribute to the
	 * {@link module:engine/model/document~Document#selection} itself (note that typed characters copy attributes from the selection).
	 * * If the selection is collapsed in an empty node, the command applies the attribute to the parent node of the selection (note
	 * that the selection inherits all attributes from a node if it is in an empty node).
	 *
	 * @fires execute
	 * @param {Object} [options] Command options.
	 * @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will apply the attribute,
	 * otherwise the command will remove the attribute.
	 * If not set, the command will look for its current value to decide what it should do.
	 */
	execute( {value}) {
		const editor = this.editor;
		const model = editor.model;
		const doc = model.document;

		model.change( writer => {
			// Get only those blocks from selected that can have alignment set
			const blocks = Array.from( doc.selection.getSelectedBlocks() );
			const intentProp = blocks[ 0 ].getAttribute( INDENT );
			if(intentProp!=null){
				setIndentOnSelection( blocks, writer, parseFloat(intentProp)-20 );
			}
		} );

	}


	/**
	 * Checks whether a block can have alignment set.
	 *
	 * @private
	 * @param {module:engine/model/element~Element} block The block to be checked.
	 * @returns {Boolean}
	 */
	_canBeAligned( block ) {
		return this.editor.model.schema.checkAttribute( block, 'Indent' );
	}
}

// Sets the alignment attribute on blocks.
// @private
function setIndentOnSelection( blocks, writer, alignment ) {
	for ( const block of blocks ) {
		writer.setAttribute( INDENT, alignment, block );
	}
}
